package com.application.race.manage.player;
import com.application.race.manage.DEF;
import com.application.race.manage.MapInfo;
public class ConflictChecker {
	Player car;
	MapInfo mapInfo;
	static int int16 = 16;
	static int int0 = 0;
	static int int1 = 1;
	static int int_1 = -1;
	static double d1d5 = 1.5;
	public ConflictChecker(Player car) {
		this.car = car;
		this.mapInfo = car.mapInfo;
		half = car.carInfo.confRadius / 2;
	}

	boolean hasConflict = false;
	int x_flg, y_flg;
	double xx, yy, divx, divy;
	double abs_x_off ;
	double abs_y_off ;
	boolean hadCrash;
	public void checkConflict(double x_off, double y_off) {
		if (x_off == int0 && y_off == int0)
			return;
		// trace("offf   "+x_off+"  "+y_off);
		if (x_off < int0) {
			x_dir = DEF.DIRECTION_LEFT;
			x_flg = int_1;
		} else {
			x_dir = DEF.DIRECTION_RIGHT;
			x_flg = int1;
		}

		if (y_off < int0) {
			y_dir = DEF.DIRECTION_UP;
			y_flg = int_1;
		} else {
			y_dir = DEF.DIRECTION_DOWN;
			y_flg = int1;
		}
		divx = int0;
		divy = int0;
		abs_x_off = Math.abs(x_off);
		abs_y_off = Math.abs(y_off);
		// moveLogic(abs_x_off,abs_y_off);
		if (abs_x_off > abs_y_off) {
			divx = abs_y_off / abs_x_off;
			if (abs_x_off > int16) {
				while (abs_x_off > int0) {
					if (abs_x_off > int16) {
						xx = int16;
					} else {
						xx = abs_x_off;
					}
					abs_x_off -= xx;
					yy = xx * divx;
					// abs_y_off-=yy;
					hadCrash = moveLogic(xx, yy);
					if (hadCrash)
						return;
				}
			} else {
				moveLogic(Math.abs(x_off), Math.abs(y_off));
				return;
			}
		} else {
			divy = abs_x_off / abs_y_off;
			if (abs_y_off > int16) {

				while (abs_y_off > int0) {
					if (abs_y_off > int16) {
						yy = int16;
					} else {
						yy = abs_y_off;
					}
					abs_y_off -= yy;
					xx = yy * divy;
					// abs_x_off-=xx;
					hadCrash = moveLogic(xx, yy);
					if (hadCrash)
						return;
				}
			} else {
				moveLogic(Math.abs(x_off), Math.abs(y_off));
			}
		}

	}

	double x0,y0,x1, y1;
	boolean crash_x, crash_y;

	Boolean moveLogic(double xx, double yy) {
		x0 = xx * x_flg;
		y0 = yy * y_flg;
		crash_x = actorMoveInPhyLayerX(x0, y0);

		crash_y = actorMoveInPhyLayerY(x0, y0);

		if (crash_x || crash_y) {
			if (x_crash_length > int1 && y_crash_length > int1) {//  
				crashActionXY();
			} else if (x_crash_length == int0 || y_crash_length > int1) {//  
				crashActionY(xx, yy);
			} else if (y_crash_length == int0 || x_crash_length > int1) {//  
				crashActionX(xx, yy);
			} else {//  
				crashActionXY();
			}
			// trace(car._x+"  crash  "+car._y+"   "+y_crash_length+"  "+x_crash_length);
			return retb=true;
		}
		car._x += xx * x_flg;
		car._y += yy * y_flg;
		// trace(car._x+"     "+car._y);
		return retb=false;
	}

	void crashActionXY() {
		// trace("X  Y");
		car._x = x1;
		car._y = y1;
		number=car._vx * int_1 / d1d5;
		number1=car._vy * int_1 / d1d5;
		car.sideClipContrl.addCrash(number,number1);

	}

	// 单边碰撞
	void crashActionX(double xx, double yy) {
		// trace(car._x+" xxx crash  "+x1*x_flg
		// +"   "+x_crash_length+"  "+y_crash_length);
		car._x = x1;
		car._y += yy * y_flg;
		number=car._vx * int_1 / d1d5;
		number1=car._vy / d1d5;
		car.sideClipContrl.addCrash(number, number1);
	}

	void crashActionY(double xx, double yy) {
		// trace(car._y+" YYY crash  "+y1*y_flg
		// +"   "+y_crash_length+"  "+x_crash_length);
		car._x += xx * x_flg;
		car._y = y1;
		number=car._vx / d1d5;
		number1=car._vy * int_1 / d1d5;
		car.sideClipContrl.addCrash(number, number1);

	}

	double number;
	double number1;
	int x_crash_length, y_crash_length;

	boolean actorMoveInPhyLayerX(double x_off, double y_off) {
		x = car._x + x_off;
		y = car._y + y_off;
		left_x = x - half;
		right_x = x + half;
		up_y = y - half;
		down_y = y + half;

		x_crash_length = int0;
		x1 = x;
		switch (x_dir) {
		case DEF.DIRECTION_LEFT:
			 
			x_block = (int) Math.floor(number=left_x / int16);
			
			o_x_block = (int) Math.floor(number=(car._x - half) / int16);
			if (x_block < int0)
				return retb=false;
			if (o_x_block == x_block)
				return retb=false;

			start_y_block = (int) Math.floor(number=up_y / int16);
			end_y_block = (int) Math.floor(number=down_y / int16);
			if ((number=down_y % int16) == int0) {
				end_y_block--;
			}
			if(start_y_block<int0)start_y_block=int0;
			if(end_y_block>=mapInfo.height_in_tiles)end_y_block=mapInfo.height_in_tiles-int1;
			for (y_y = start_y_block; y_y <= end_y_block; y_y++) {
				intTemp = y_y * mapInfo.width_in_tiles + x_block;
				if (!pointCanPass(intTemp)) {
					// / trace("x_block "+x_block)
					x_crash_length++;

				}
			}
			if (x_crash_length > int0) {
				x1 = x_block * int16 + int16 + half;
				return retb=true;
			}
			break;
		case DEF.DIRECTION_RIGHT:

			x_block = (int) Math.floor(number=right_x / int16);
			o_x_block = (int) Math.floor(number=(car._x + half) / int16);
			if ((number=(car._x + half) % int16) == int0) {
				o_x_block--;
			}
			if ((number=right_x % int16) == int0) {
				x_block--;
			}
			// trace("x1   "+x_off+"  "+(right_x%int16));
			// if(x1<int0||x1>Math.abs(x_off))x1=Math.abs(x_off);
			if (x_block >= mapInfo.width_in_tiles)
				return retb=false;
			if (o_x_block == x_block)
				return retb=false;

			start_y_block = (int) Math.floor(number=up_y / int16);
			end_y_block = (int) Math.floor(number=down_y / int16);
			if ((number=down_y % int16) == int0) {
				end_y_block--;
			}
			if(start_y_block<int0)start_y_block=int0;
			if(end_y_block>=mapInfo.height_in_tiles)end_y_block=mapInfo.height_in_tiles-int1;
			for (y_y = start_y_block; y_y <= end_y_block; y_y++) {
				intTemp = y_y * mapInfo.width_in_tiles + x_block;
				if (!pointCanPass(intTemp)) {
					x_crash_length++;
					// trace("x1   "+x_off+"  "+(right_x%int16));
				}

			}
			if (x_crash_length > int0) {
				x1 = x_block * int16 - half;
				return retb=true;
			}
			break;
		}
		return retb=false;
	}

	int start_x_block, end_x_block, start_y_block, end_y_block,y_block,x_block;
	double half, left_x, right_x, up_y, down_y, kk;
	int x_dir, y_dir,x_x,y_y,o_x_block,o_y_block;
	int intTemp = int0;
    double x,y;
	public boolean actorMoveInPhyLayerY(double x_off, double y_off) {
		x = car._x + x_off;
		y = car._y + y_off;
		left_x = x - half;
		right_x = x + half;
		up_y = y - half;
		down_y = y + half;

		y_crash_length = int0;
		y1 = y;
		switch (y_dir) {
		case DEF.DIRECTION_UP:
			y_block = (int) Math.floor(number=up_y / int16);
			o_y_block = (int) Math.floor(number=(car._y - half) / int16);

			if (y_block < int0)
				return retb=false;
			if (o_y_block == y_block)
				return retb=false;
			start_x_block = (int) Math.floor(number=left_x / int16);

			end_x_block = (int) Math.floor(number=right_x / int16);
			if ((number=right_x % int16) == int0) {
				end_x_block--;
			}
			if(start_x_block<int0)start_x_block=int0;
			if(end_x_block>=mapInfo.width_in_tiles)end_x_block=mapInfo.width_in_tiles-int1;
			for ( x_x = start_x_block; x_x <= end_x_block; x_x++) {
				intTemp = y_block * mapInfo.width_in_tiles + x_x;
				if (!pointCanPass(intTemp)) {
					y_crash_length++;
				}
			}
			if (y_crash_length > int0) {
				y1 = y_block * int16 + int16 + half;
				return retb=true;
			}
			break;
		case DEF.DIRECTION_DOWN:
			y_block = (int) Math.floor(number=down_y / int16);
			o_y_block = (int) Math.floor(number=(car._y + half) / int16);
			if ((number=(car._y + half)) % int16 == int0) {
				o_y_block--;
			}
			if ((number=down_y % int16) == int0) {
				y_block--;
			}
			// if(y1<int0||y1>Math.abs(y_off))y1=Math.abs(y_off);
			if (y_block >= mapInfo.height_in_tiles)
				return retb=false;
			if (o_y_block == y_block)
				return retb=false;

			start_x_block = (int) Math.floor(number=left_x / int16);
			end_x_block = (int) Math.floor(number=right_x / int16);
			if ((number=right_x % int16) == int0) {
				end_x_block--;
			}
			if(start_x_block<int0)start_x_block=int0;
			if(end_x_block>=mapInfo.width_in_tiles)end_x_block=mapInfo.width_in_tiles-int1;
			for (x_x = start_x_block; x_x <= end_x_block; x_x++) {
				intTemp = y_block * mapInfo.width_in_tiles + x_x;
				if (!pointCanPass(intTemp)) {

					y_crash_length++;
				}
			}
			if (y_crash_length > int0) {
				y1 = y_block * int16 - half;
				return retb=true;
			}
			break;

		}

		return retb=false;
	}
	private boolean retb=false;
	boolean pointCanPass(int i) {
		switch ( mapInfo.physIdx[i]) {
		case DEF.TILE_TYPE_BUILDING:
		//case DEF.TILE_TYPE_NOTPASS:
			// trace("no pass");
			
			return retb=false;
		default:
			return retb=true;
		}
	}

}
